﻿using MediatR;
using Newtonsoft.Json;
using Service.Auth.Domain.AggregatesModel;
using Service.Core.Identity;
using Service.Core.Identity.Login;
using Service.Core.Identity.Model;
using Service.Core.Redis.Services;
using Service.Core.Repository;
using Service.Core.Repository.Attribute;
using Service.Core.Repository.UnitOfWorks;
using Service.Framework;
using Service.Framework.Utils.Helper;
using Service.Auth.Api.Application.Command;
using Service.Auth.Api.Application.Query;

namespace Service.Auth.Api.Application.Handler.CommandHandler;


/// <summary>
/// 
/// </summary>
/// <param name="roleRepository"></param>
/// <param name="rolePermissionRepository"></param>
/// <param name="systemRepository"></param>
/// <param name="rolePemissionsQueryService"></param>
/// <param name="unitOfWorkManage"></param>
/// <param name="redisService"></param>
/// <param name="loginUserSession"></param>
public class RoleCommandHandler(
    IRepository<Role> roleRepository,
    IRepository<RolePermission> rolePermissionRepository,
    IRepository<TSystem> systemRepository,
    RolePemissionsQueryService rolePemissionsQueryService,
    IUnitOfWorkManage unitOfWorkManage,
    IRedisService redisService,
    ILoginUserSession loginUserSession)
    :
        IRequestHandler<CreateRoleCommand, bool>,
        IRequestHandler<UpdateRoleCommand, bool>,
        IRequestHandler<DeleteRoleCommand, bool>,
        IRequestHandler<RoleBindPermissionsCommand, bool>
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="LogicErrorException"></exception>
    [UnitOfWork]
    public async Task<bool> Handle(CreateRoleCommand request, CancellationToken cancellationToken)
    {
        var roleDto = request.Role;
        if (await roleRepository.AnyAsync(s => s.RoleNum.Equals(roleDto.RoleNum), cancellationToken))
            throw new LogicErrorException($"角色编号：{roleDto.RoleNum}重复，请修改后重试。");
        if (!await systemRepository.AnyAsync(s => s.Id.Equals(roleDto.SystemId), cancellationToken))
            throw new LogicErrorException($"系统不存在，请修改后重试。");
        //提供默认角色等级，只有管理员才可以修改用户角色等级
        var role = new Role(SnowflakeUtil.Instance().GetId(), roleDto.RoleNum, roleDto.RoleName, roleDto.Remarks, 1, roleDto.SystemId);
        return await roleRepository.InsertAsync(role, cancellationToken);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    [UnitOfWork]
    public async Task<bool> Handle(UpdateRoleCommand request, CancellationToken cancellationToken)
    {
        var roleDto = request.Role;
        var role = await roleRepository.GetByIdAsync(roleDto.Id, cancellationToken);
        CheckLevel(role);
        //值只修改固定字段，保证代码数据安全性
        role.SetRoleNum(roleDto.RoleNum);
        role.SetRoleName(roleDto.RoleName);
        role.SetRemarks(roleDto.Remarks);
        return await roleRepository.UpdateAsync(role, cancellationToken);
    }

    [UnitOfWork]
    public async Task<bool> Handle(DeleteRoleCommand request, CancellationToken cancellationToken)
    {
        var roleDto = request.Role;
        var role = await roleRepository.GetByIdAsync(roleDto.Id, cancellationToken);
        CheckLevel(role);
        return await roleRepository.DeleteAsync(role, cancellationToken);
    }

    /// <summary>
    /// 角色权限刷新后，需要刷新缓存，不然会导致请求401
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    //[UnitOfWork]
    public async Task<bool> Handle(RoleBindPermissionsCommand request, CancellationToken cancellationToken)
    {

        try
        {
            var roleBindPermissionsDto = request.RoleBindPermissions;
            if (!unitOfWorkManage.HasActiveTransaction())
            {
                unitOfWorkManage.BeginTran();
            }
            var addData = new List<RolePermission>();
            var rolePermissions = await rolePermissionRepository.GetListAsync(s => s.RoleId.Equals(roleBindPermissionsDto.Id), cancellationToken: cancellationToken);
            if (rolePermissions is { Count: > 0 })
            {
                var rolePermissionsIds = rolePermissions.Select(s => s.PermissionId).ToList();
                var deleteData = rolePermissionsIds.Except(roleBindPermissionsDto.PrmissionIds).ToList();
                if (deleteData is { Count: > 0 })
                {
                    var deleterolePermissions = rolePermissions.Where(s => deleteData.Contains(s.PermissionId)).ToList();
                    await rolePermissionRepository.DeleteRangeAsync(deleterolePermissions, cancellationToken);
                }

                var addIdsData = roleBindPermissionsDto.PrmissionIds.Except(rolePermissionsIds).ToList();
                if (addIdsData is { Count: > 0 })
                {
                    addData.AddRange(addIdsData.Select(s => new RolePermission(roleBindPermissionsDto.Id, s)));
                }
            }
            else
            {
                addData.AddRange(roleBindPermissionsDto.PrmissionIds.Select(s => new RolePermission(roleBindPermissionsDto.Id, s)));
            }
            if (addData.Count > 0)
            {
                await rolePermissionRepository.InsertRangeAsync(addData, cancellationToken);
            }
            unitOfWorkManage.CommitTran();
            return true;
        }
        catch (Exception e)
        {
            unitOfWorkManage.RollbackTran();
            throw new LogicErrorException(e.Message);
        }
        finally
        {
            var items = await rolePemissionsQueryService.QueryRolePemissionItem();
            await redisService.Database.StringSetAsync(DefaultRedisKeys.PermissionKey, JsonConvert.SerializeObject(items));
        }
        //刷新下缓存
        //return true;
    }

    private void CheckLevel(Role role)
    {
        var userInfo = loginUserSession.UserInfo;
        if (role == null)
            throw new LogicErrorException("操作失败，角色不存在。");
        if (role.Default)
            throw new LogicErrorException("操作失败，系统默认角色不能操作。");
        if (!userInfo.Roles.Contains(Permissions.SysAdmin) && userInfo.Roles.Any(s => s.Equals(role.RoleNum)))
            throw new LogicErrorException("请求失败，不能操作与自己相关的角色。");
        if (userInfo.RoleMaxLevel <= role.Level)
            throw new LogicErrorException("请求失败，当前用户角色级别不够。");
    }


}

